#include "jsapi.h"
#include "js-engine.h"
#include "desktopClasses.h"
#include "basicElementClass.h"
#include "mainview-parser.h"
#define DEFAULT_FONT_FAMILY "Sans"

static const PangoColor default_label_color = {0,0,0};
static JSBool label_new(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval);
static JSBool label_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);

static JSFunctionSpec label_methods[] = {
    {NULL, NULL, 0, 0, 0}
};

JSClass labelClass =
    { "label", JSCLASS_HAS_PRIVATE,
      JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, label_SetProperty,
      JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
      JSCLASS_NO_OPTIONAL_MEMBERS
    };

struct property_parser label_parser[] = {
    /* from basicElement */
    {"cursor", set_property_string_value},
    {"dropTarget", set_property_boolean_value},
    {"enabled", set_property_boolean_value},
    {"height", set_property_integer_value},
    {"hitTest", set_property_string_value},
    {"mask", set_property_string_value},
    {"name", set_property_string_value},
    {"offsetHeight", set_property_integer_value},
    {"offsetWidth", set_property_integer_value},
    {"offsetX", set_property_integer_value},
    {"offsetY", set_property_integer_value},
    {"opacity", set_property_integer_value},
    {"pinX", set_property_integer_value},
    {"pinY", set_property_integer_value},
    {"rotation", set_property_float_value},
    {"tagName", set_property_string_value},
    {"tooltip", set_property_string_value},
    {"width", set_property_string_value},
    {"visible", set_property_boolean_value},
    {"x", set_property_integer_value},
    {"y", set_property_integer_value},
                
    {"align", set_property_string_value},
    {"bold", set_property_boolean_value},
    {"color", set_property_string_value},
    {"font", set_property_string_value},
    {"innerText", set_property_string_value},
    {"italic", set_property_boolean_value},
    {"size", set_property_integer_value},
    {"strikeout", set_property_boolean_value},
    {"trimming", set_property_string_value},
    {"underline", set_property_boolean_value},
    {"vAlign", set_property_string_value},
    {"wordWrap", set_property_boolean_value},
    {NULL, NULL},
};

static JSBool label_new(JSContext *cx, JSObject *obj, uintN argc, jsval *args, jsval *rval) {
    return JS_TRUE;
}

JSObject *labelClass_init(js_engine *engine, JSObject *parent) {
    JSObject *proto= NULL;
    proto = JS_InitClass(engine->cx, engine->glob, parent, &labelClass,
                         label_new, 0, NULL, NULL, NULL, NULL);
    g_return_val_if_fail(proto, FALSE);
    g_return_val_if_fail(JS_DefineFunctions(engine->cx, proto, label_methods),
                         FALSE);
    return proto;
}

JSBool label_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) {
    desktop_element *element = JS_GetPrivate(cx, obj);
    if (!element || !element->view)
        return JS_TRUE;
    
    basicElement_SetProperty(cx, obj, id, vp);
    gtk_widget_queue_draw(element->view);    
    return JS_TRUE;
}

gboolean draw_label(GtkWidget *event_box, GdkEventExpose *event, gpointer ptr) {
    desktop_element *element = (desktop_element *)ptr;
    gint window_x, window_y;
    cairo_t *cr = gdk_cairo_create(event_box->window);
    PangoLayout *layout = pango_cairo_create_layout(cr);
    PangoAttrList *list = pango_attr_list_new();
    PangoAttribute *attr= NULL;
    PangoRectangle rect;
    gdouble text_width, text_height;
    gchar *alignStr = NULL, *vAlignStr = NULL;
    gint label_width = -1, label_height = -1;

    jsval x, y, opacity, align, bold, color, font, innerText, italic,
        overColor, size, strikeout, trimming, underline, vAlign, height,
        width, wordWrap;

    gint fontSize= DEFAULT_FONT_SIZE;
    gdouble x_pos = 0, y_pos = 0, opacity_ratio = 0;

    gdk_drawable_get_size(element->view->window, &window_x, &window_y);

    JS_GetProperty(element->engine->cx, element->jsobj, "x", &x);
    JS_GetProperty(element->engine->cx, element->jsobj, "y", &y);
    JS_GetProperty(element->engine->cx, element->jsobj, "align", &align);
    JS_GetProperty(element->engine->cx, element->jsobj, "bold", &bold);
    JS_GetProperty(element->engine->cx, element->jsobj, "color", &color);
    JS_GetProperty(element->engine->cx, element->jsobj, "font", &font);
    JS_GetProperty(element->engine->cx, element->jsobj, "innerText", &innerText);
    JS_GetProperty(element->engine->cx, element->jsobj, "italic", &italic);
    JS_GetProperty(element->engine->cx, element->jsobj, "opacity", &opacity);
    JS_GetProperty(element->engine->cx, element->jsobj, "overColor", &overColor);
    JS_GetProperty(element->engine->cx, element->jsobj, "size", &size);
    JS_GetProperty(element->engine->cx, element->jsobj, "strikeout", &strikeout);
    JS_GetProperty(element->engine->cx, element->jsobj, "trimming", &trimming);
    JS_GetProperty(element->engine->cx, element->jsobj, "underline", &underline);
    JS_GetProperty(element->engine->cx, element->jsobj, "vAlign", &vAlign);
    JS_GetProperty(element->engine->cx, element->jsobj, "height", &height);
    JS_GetProperty(element->engine->cx, element->jsobj, "width", &width);
    JS_GetProperty(element->engine->cx, element->jsobj, "wordWrap", &wordWrap);

    if (JSVAL_IS_NUMBER(x))
        JS_ValueToNumber(element->engine->cx, x, &x_pos);
    if (JSVAL_IS_NUMBER(y))
        JS_ValueToNumber(element->engine->cx, y, &y_pos);

    if(JSVAL_IS_PRIMITIVE(innerText)){
	GString *innerTextString = 
	    g_string_new(JS_GetStringBytes(JS_ValueToString(element->engine->cx, innerText)));
        pango_layout_set_text(layout, innerTextString->str,
                              innerTextString->len);
	g_string_free(innerTextString, TRUE);
    }

    if (JSVAL_IS_INT(opacity)) {
        int value= JSVAL_TO_INT(opacity);
        opacity_ratio = (gdouble)value/255;
    }

    if (JSVAL_IS_BOOLEAN(bold) && JSVAL_TO_BOOLEAN(bold)) {
        attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    }

    if (JSVAL_IS_STRING(color)) {
        PangoColor color_val = default_label_color;
        pango_color_parse(&color_val, JS_GetStringBytes(JSVAL_TO_STRING(color)));
        attr = pango_attr_foreground_new(color_val.red, color_val.green,
                                         color_val.blue);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    }

    if (JSVAL_IS_STRING(font)) {
        attr = pango_attr_family_new(JS_GetStringBytes(JSVAL_TO_STRING(font)));
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    } else {
        attr = pango_attr_family_new(DEFAULT_FONT_FAMILY);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    }

    if (JSVAL_IS_BOOLEAN(italic) && JSVAL_TO_BOOLEAN(italic)) {
        attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    }

    if (JSVAL_IS_STRING(overColor)) {
        gchar *overColorStr = JS_GetStringBytes(JSVAL_TO_STRING(overColor));
    }

    if (JSVAL_IS_INT(size)) {
        fontSize = JSVAL_TO_INT(size);
        attr = pango_attr_size_new(fontSize*PANGO_SCALE);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    } else {
        attr = pango_attr_size_new(fontSize*PANGO_SCALE);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    }

    if (JSVAL_IS_BOOLEAN(strikeout) && JSVAL_TO_BOOLEAN(strikeout)) {
        attr = pango_attr_strikethrough_new(TRUE);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    }

    if (JSVAL_IS_STRING(trimming)) {
        gchar *trimmingStr = JS_GetStringBytes(JSVAL_TO_STRING(trimming));
    }

    if (JSVAL_IS_BOOLEAN(underline) && JSVAL_TO_BOOLEAN(underline)) {
        attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
        attr->start_index = 0;
        attr->end_index = -1;
        pango_attr_list_insert(list, attr);
    }

    if (JSVAL_IS_BOOLEAN(wordWrap)) {
        /*
          isWordWrap = JSVAL_TO_BOOLEAN(wordWrap);
        */
    }

    pango_layout_set_attributes(layout, list);
    pango_layout_get_extents(layout, &rect, NULL);

    text_width = rect.width/PANGO_SCALE;    
    text_height = rect.height/PANGO_SCALE;    
    if (JSVAL_IS_STRING(align))
	alignStr = JS_GetStringBytes(JSVAL_TO_STRING(align));

    if (JSVAL_IS_STRING(width)){
	GString *width_str = g_string_new(JS_GetStringBytes(JSVAL_TO_STRING(width)));
	if(width_str->str[width_str->len-1] == '%') {
	    guint64 width_percentage;
	    width_str->str[width_str->len-1] = '\0';
	    width_percentage = g_ascii_strtoull(width_str->str, NULL, 10);
	    label_width = window_x * width_percentage/100;
	}else{
	    label_width = (gint)g_ascii_strtoull(width_str->str, NULL, 10);
	}
	g_string_free(width_str, TRUE);
    } else if(JSVAL_IS_INT(width)) {
	label_width = JSVAL_TO_INT(width);
    } else {
	label_width = text_width;
    }

    if(alignStr == NULL){  
    }else if(g_strcasecmp(alignStr, "center") == 0){
	x_pos += (gdouble)(label_width-(gdouble)text_width)/2;
    }else if(g_strcasecmp(alignStr, "right") == 0){
	x_pos +=(gdouble)(label_width-(gdouble)text_width);
    }else{
    }

    if(JSVAL_IS_STRING(vAlign))
        vAlignStr = JS_GetStringBytes(JSVAL_TO_STRING(vAlign));

    if(JSVAL_IS_STRING(height)){
	GString *height_str = g_string_new(JS_GetStringBytes(JSVAL_TO_STRING(height)));
	if(height_str->str[height_str->len-1] == '%'){
	    guint64 height_percentage;
	    height_str->str[height_str->len-1] = '\0';
	    height_percentage = g_ascii_strtoull(height_str->str, NULL, 10);
	    label_height = window_y * height_percentage/100;
	}else{
	    label_height = (gint)g_ascii_strtoull(height_str->str, NULL, 10);
	}
	g_string_free(height_str, TRUE);
    }else if(JSVAL_IS_INT(height)){
	label_height = JSVAL_TO_INT(height);
    }else{
	label_height = text_height;
    }

    if(vAlignStr == NULL){  
    }else if(g_strcasecmp(vAlignStr, "center") == 0){
	y_pos += (gdouble)(label_height-(gdouble)text_height)/2;
    }else if(g_strcasecmp(vAlignStr, "right") == 0){
	y_pos +=(gdouble)(label_height-(gdouble)text_height);
    }else{
    }

    cairo_move_to(cr, x_pos, y_pos);
    if(JSVAL_IS_VOID(height) && JSVAL_IS_VOID(width)){
	gtk_widget_set_size_request(element->view, (gint)text_width+2, (gint)text_height+2);
    }
    pango_cairo_show_layout(cr, layout);
    cairo_destroy(cr);
    return FALSE;
}

void desktop_element_set_view_label(js_engine *engine, desktop_element *element) {
    element->view = gtk_event_box_new();
    gtk_event_box_set_visible_window(GTK_EVENT_BOX(element->view), FALSE);
    gtk_widget_set_app_paintable (element->view, TRUE);
    g_signal_connect(element->view, "expose-event", G_CALLBACK(draw_label),
                     element);
    gtk_widget_show_all(element->view);
    set_element_event_cb(element);
}
